/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dataAccess;

import dataAccess.exceptions.NonexistentEntityException;
import dataAccess.exceptions.PreexistingEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entities.Role;
import entities.Report;
import java.util.ArrayList;
import java.util.List;
import entities.TimeTable;
import entities.Users;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author QUY-THI
 */
public class UsersJpaController implements Serializable {

    public UsersJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Users users) throws PreexistingEntityException, Exception {
        if (users.getReportList() == null) {
            users.setReportList(new ArrayList<Report>());
        }
        if (users.getTimeTableList() == null) {
            users.setTimeTableList(new ArrayList<TimeTable>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Role roleID = users.getRoleID();
            if (roleID != null) {
                roleID = em.getReference(roleID.getClass(), roleID.getRoleID());
                users.setRoleID(roleID);
            }
            List<Report> attachedReportList = new ArrayList<Report>();
            for (Report reportListReportToAttach : users.getReportList()) {
                reportListReportToAttach = em.getReference(reportListReportToAttach.getClass(), reportListReportToAttach.getReportID());
                attachedReportList.add(reportListReportToAttach);
            }
            users.setReportList(attachedReportList);
            List<TimeTable> attachedTimeTableList = new ArrayList<TimeTable>();
            for (TimeTable timeTableListTimeTableToAttach : users.getTimeTableList()) {
                timeTableListTimeTableToAttach = em.getReference(timeTableListTimeTableToAttach.getClass(), timeTableListTimeTableToAttach.getId());
                attachedTimeTableList.add(timeTableListTimeTableToAttach);
            }
            users.setTimeTableList(attachedTimeTableList);
            em.persist(users);
            if (roleID != null) {
                roleID.getUsersList().add(users);
                roleID = em.merge(roleID);
            }
            for (Report reportListReport : users.getReportList()) {
                Users oldSenderOfReportListReport = reportListReport.getSender();
                reportListReport.setSender(users);
                reportListReport = em.merge(reportListReport);
                if (oldSenderOfReportListReport != null) {
                    oldSenderOfReportListReport.getReportList().remove(reportListReport);
                    oldSenderOfReportListReport = em.merge(oldSenderOfReportListReport);
                }
            }
            for (TimeTable timeTableListTimeTable : users.getTimeTableList()) {
                Users oldUserIDOfTimeTableListTimeTable = timeTableListTimeTable.getUserID();
                timeTableListTimeTable.setUserID(users);
                timeTableListTimeTable = em.merge(timeTableListTimeTable);
                if (oldUserIDOfTimeTableListTimeTable != null) {
                    oldUserIDOfTimeTableListTimeTable.getTimeTableList().remove(timeTableListTimeTable);
                    oldUserIDOfTimeTableListTimeTable = em.merge(oldUserIDOfTimeTableListTimeTable);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findUsers(users.getUserID()) != null) {
                throw new PreexistingEntityException("Users " + users + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Users users) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Users persistentUsers = em.find(Users.class, users.getUserID());
            Role roleIDOld = persistentUsers.getRoleID();
            Role roleIDNew = users.getRoleID();
            List<Report> reportListOld = persistentUsers.getReportList();
            List<Report> reportListNew = users.getReportList();
            List<TimeTable> timeTableListOld = persistentUsers.getTimeTableList();
            List<TimeTable> timeTableListNew = users.getTimeTableList();
            if (roleIDNew != null) {
                roleIDNew = em.getReference(roleIDNew.getClass(), roleIDNew.getRoleID());
                users.setRoleID(roleIDNew);
            }
            List<Report> attachedReportListNew = new ArrayList<Report>();
            for (Report reportListNewReportToAttach : reportListNew) {
                reportListNewReportToAttach = em.getReference(reportListNewReportToAttach.getClass(), reportListNewReportToAttach.getReportID());
                attachedReportListNew.add(reportListNewReportToAttach);
            }
            reportListNew = attachedReportListNew;
            users.setReportList(reportListNew);
            List<TimeTable> attachedTimeTableListNew = new ArrayList<TimeTable>();
            for (TimeTable timeTableListNewTimeTableToAttach : timeTableListNew) {
                timeTableListNewTimeTableToAttach = em.getReference(timeTableListNewTimeTableToAttach.getClass(), timeTableListNewTimeTableToAttach.getId());
                attachedTimeTableListNew.add(timeTableListNewTimeTableToAttach);
            }
            timeTableListNew = attachedTimeTableListNew;
            users.setTimeTableList(timeTableListNew);
            users = em.merge(users);
            if (roleIDOld != null && !roleIDOld.equals(roleIDNew)) {
                roleIDOld.getUsersList().remove(users);
                roleIDOld = em.merge(roleIDOld);
            }
            if (roleIDNew != null && !roleIDNew.equals(roleIDOld)) {
                roleIDNew.getUsersList().add(users);
                roleIDNew = em.merge(roleIDNew);
            }
            for (Report reportListOldReport : reportListOld) {
                if (!reportListNew.contains(reportListOldReport)) {
                    reportListOldReport.setSender(null);
                    reportListOldReport = em.merge(reportListOldReport);
                }
            }
            for (Report reportListNewReport : reportListNew) {
                if (!reportListOld.contains(reportListNewReport)) {
                    Users oldSenderOfReportListNewReport = reportListNewReport.getSender();
                    reportListNewReport.setSender(users);
                    reportListNewReport = em.merge(reportListNewReport);
                    if (oldSenderOfReportListNewReport != null && !oldSenderOfReportListNewReport.equals(users)) {
                        oldSenderOfReportListNewReport.getReportList().remove(reportListNewReport);
                        oldSenderOfReportListNewReport = em.merge(oldSenderOfReportListNewReport);
                    }
                }
            }
            for (TimeTable timeTableListOldTimeTable : timeTableListOld) {
                if (!timeTableListNew.contains(timeTableListOldTimeTable)) {
                    timeTableListOldTimeTable.setUserID(null);
                    timeTableListOldTimeTable = em.merge(timeTableListOldTimeTable);
                }
            }
            for (TimeTable timeTableListNewTimeTable : timeTableListNew) {
                if (!timeTableListOld.contains(timeTableListNewTimeTable)) {
                    Users oldUserIDOfTimeTableListNewTimeTable = timeTableListNewTimeTable.getUserID();
                    timeTableListNewTimeTable.setUserID(users);
                    timeTableListNewTimeTable = em.merge(timeTableListNewTimeTable);
                    if (oldUserIDOfTimeTableListNewTimeTable != null && !oldUserIDOfTimeTableListNewTimeTable.equals(users)) {
                        oldUserIDOfTimeTableListNewTimeTable.getTimeTableList().remove(timeTableListNewTimeTable);
                        oldUserIDOfTimeTableListNewTimeTable = em.merge(oldUserIDOfTimeTableListNewTimeTable);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = users.getUserID();
                if (findUsers(id) == null) {
                    throw new NonexistentEntityException("The users with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Users users;
            try {
                users = em.getReference(Users.class, id);
                users.getUserID();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The users with id " + id + " no longer exists.", enfe);
            }
            Role roleID = users.getRoleID();
            if (roleID != null) {
                roleID.getUsersList().remove(users);
                roleID = em.merge(roleID);
            }
            List<Report> reportList = users.getReportList();
            for (Report reportListReport : reportList) {
                reportListReport.setSender(null);
                reportListReport = em.merge(reportListReport);
            }
            List<TimeTable> timeTableList = users.getTimeTableList();
            for (TimeTable timeTableListTimeTable : timeTableList) {
                timeTableListTimeTable.setUserID(null);
                timeTableListTimeTable = em.merge(timeTableListTimeTable);
            }
            em.remove(users);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Users> findUsersEntities() {
        return findUsersEntities(true, -1, -1);
    }

    public List<Users> findUsersEntities(int maxResults, int firstResult) {
        return findUsersEntities(false, maxResults, firstResult);
    }

    private List<Users> findUsersEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Users.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Users findUsers(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Users.class, id);
        } finally {
            em.close();
        }
    }

    public int getUsersCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Users> rt = cq.from(Users.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
